package xcmg.device.service.materialsSchedule;

import com.github.pagehelper.PageInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import xcmg.device.dao.entity.DataDictionaryDO;
import xcmg.device.dao.entity.delivery.DeliveryNoteDO;
import xcmg.device.dao.entity.materialsSchedule.MaterialsScheduleDO;
import xcmg.device.dao.entity.materialsSchedule.MaterialsScheduleDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundDetailDO;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.DataDictionaryMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteDetailMapper;
import xcmg.device.dao.mapper.delivery.DeliveryNoteMapper;
import xcmg.device.dao.mapper.materialsSchedule.MaterialsScheduleDetailMapper;
import xcmg.device.dao.mapper.materialsSchedule.MaterialsScheduleMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseAreaLocationDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundDetailMapper;
import xcmg.device.infra.CompanyConstants;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExcelUtil;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.infra.enums.MaterialsScheduleAuditStatusEnum;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.MaterialsService;
import xcmg.device.service.basic.SystemParameterService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.basic.MaterialsVO;
import xcmg.device.service.vo.delivery.DeliveryNoteVO;
import xcmg.device.service.vo.materialsSchedule.MaterialsScheduleAddVO;
import xcmg.device.service.vo.materialsSchedule.MaterialsScheduleDeliveryNoteDetailVO;
import xcmg.device.service.vo.materialsSchedule.MaterialsScheduleDetailVO;
import xcmg.device.service.vo.materialsSchedule.MaterialsScheduleVO;
import xcmg.device.service.vo.materialsSchedule.SelectDeliveryNoteVO;
import xcmg.device.service.vo.warehouse.FindMaterialsInfos;
import xcmg.device.service.vo.warehouse.FindMaterialsNumParam;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryAddVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryDetailVO;
import xcmg.device.service.vo.warehouse.WarehouseDeliveryVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundAddVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundDetailVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundVO;
import xcmg.device.service.vo.warehouse.sap.ObligateHeaderVO;
import xcmg.device.service.vo.warehouse.sap.ObligateVO;
import xcmg.device.service.warehouse.WarehouseDeliveryService;
import xcmg.device.service.warehouse.WarehouseInboundService;
import xcmg.device.service.warehouse.WarehouseInventoryService;
import xcmg.device.util.CompanyUtil;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MaterialsScheduleService {

    @Autowired
    private SystemParameterService systemParameterService;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private MaterialsScheduleMapper materialsScheduleMapper;

    @Autowired
    private MaterialsScheduleDetailMapper materialsScheduleDetailMapper;

    @Autowired
    private WarehouseInboundService warehouseInboundService;

    @Autowired
    private WarehouseDeliveryService warehouseDeliveryService;

    @Autowired
    private MaterialsService materialsService;

    @Autowired
    private WarehouseInboundDetailMapper warehouseInboundDetailMapper;

    @Autowired
    private WarehouseDeliveryDetailMapper warehouseDeliveryDetailMapper;
    @Autowired
    private WarehouseAreaLocationDOMapper warehouseAreaLocationDOMapper;

    @Autowired
    private DataDictionaryMapper dataDictionaryMapper;

    @Autowired
    private WarehouseInventoryService warehouseInventoryService;
    @Autowired
    private DeliveryNoteMapper deliveryNoteMapper;
    @Autowired
    private DeliveryNoteDetailMapper deliveryNoteDetailMapper;

    @Autowired
    private CompanyInfoMapper companyInfoMapper;

    private static final String WJ_ORG_ID = "214678683422556160";

    private static final String WJ_SAP_CODE = "9005";

    private static final String MID_WAREHOUSE_CODE = "MIDCODE";

    @Value("${sap.area.code:0}")
    private String sapCode;

    @Value("${spring.file.download.path}")
    private String filePath;
    private  String templateOutExcelFileName="MaterialsSchedule_SC.xls";
    private  String templateInExcelFileName="MaterialsSchedule_BJ.xls";

    /**
     * 状态：0 未开始，1 进行中，2 已完成，3 强制结单
     */
    private static final Integer STATUS_FINISH = 2, STATUS_END = 3;

    private static final Logger logger = LoggerFactory.getLogger(MaterialsScheduleService.class);

    @Autowired
    private CompanyUtil companyUtil;


    /**
     * 新增领料单
     * @param materialsScheduleAddVO
     * @param orgId
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public synchronized ErrorCode add(MaterialsScheduleAddVO materialsScheduleAddVO,String orgId) throws Exception{

        String realSapCode = sapCode;
        DataDictionaryDO dictionaryDO = dataDictionaryMapper.itemByCode(CompanyConstants.MID_WAREHOUSE_CODE, orgId);
        if (null != dictionaryDO && StringUtils.isNotBlank(dictionaryDO.getName())) {
            realSapCode = dictionaryDO.getName();
        }

        //领料主表
        MaterialsScheduleDO materialsScheduleDO = new MaterialsScheduleDO();
        BeanUtils.copyProperties(materialsScheduleAddVO.getHeaderInfo(),materialsScheduleDO);
        ActionResult<String> textSchedule = fastGenClient.textGuid();
        if (textSchedule.getCode() != ErrorCode.Success.getCode()) {
            return ErrorCode.IllegalArument;
        }
        materialsScheduleDO.setId(textSchedule.getValue().toString());
        materialsScheduleDO.setOrgId(orgId);
        materialsScheduleDO.setRequisitionNo(genDocumentService.genDocumentNo(BillDesc.MaterialsCode, orgId));
        if(materialsScheduleDO.getType().equals(0)){
            materialsScheduleDO.setDocumentName("从生产领料");
        }else {
            materialsScheduleDO.setDocumentName("从备件领料");
        }
        materialsScheduleDO.setStatus(0);
        //设置审核状态，如果事需要审核的公司则配置为审核状态为待审核，否则直接设置为审核通过
        boolean materialsScheduleAuditSetting = systemParameterService.getMaterialsScheduleAuditSetting(orgId);
        if(materialsScheduleAuditSetting){
            materialsScheduleDO.setAuditStatus(MaterialsScheduleAuditStatusEnum.AUDIT_WAIT.getAuditStatus());
        }else{
            materialsScheduleDO.setAuditStatus(MaterialsScheduleAuditStatusEnum.AUDIT_PASS.getAuditStatus());
            materialsScheduleDO.setAuditDate(new Date());
            materialsScheduleDO.setAuditUserId("0001");
            materialsScheduleDO.setAuditUserName("系统自动");
        }
        WarehouseInboundAddVO warehouseInboundAddVO=new WarehouseInboundAddVO();
        WarehouseDeliveryAddVO DeliveryAddVO = new WarehouseDeliveryAddVO();

        List<WarehouseInboundDetailVO> inDetailList = new ArrayList<WarehouseInboundDetailVO>();
        List<WarehouseDeliveryDetailVO> outDetailList = new ArrayList<WarehouseDeliveryDetailVO>();
        //领料详情表
        BigDecimal num = BigDecimal.ZERO;
        //生成区域调拨详情记录
        List<ObligateVO> obligateVOList1 = new ArrayList<>();
        List<ObligateVO> obligateVOList2 = new ArrayList<>();
        ObligateVO obligateVO1;
        ObligateVO obligateVO2;
        List<FindMaterialsInfos> infos=new ArrayList<>();
        if(materialsScheduleAddVO.getHeaderInfo().getType().equals(1)){
            for (MaterialsScheduleDetailVO detailVO:materialsScheduleAddVO.getDetailList()) {
                FindMaterialsInfos findMaterialsInfos=new FindMaterialsInfos();
                findMaterialsInfos.setMaterialsNo(detailVO.getMaterialsNo());
                findMaterialsInfos.setAmount(detailVO.getAmount());
                infos.add(findMaterialsInfos);
            }
            FindMaterialsNumParam findMaterialsNumParam=new FindMaterialsNumParam();
            findMaterialsNumParam.setMaterialsNos(infos);
            findMaterialsNumParam.setOrgId(orgId);

            findMaterialsNumParam.setWarehousCode(materialsScheduleAddVO.getHeaderInfo().getOutLocation());
            if(!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)){
                return ErrorCode.PartMaterialsNotNumber;
            }
        }

        for(MaterialsScheduleDetailVO detailVO:materialsScheduleAddVO.getDetailList()){
            MaterialsScheduleDetailDO materialsScheduleDetailDO = new MaterialsScheduleDetailDO();
            BeanUtils.copyProperties(detailVO,materialsScheduleDetailDO);
            ActionResult<String> textScheduleDetail=fastGenClient.textGuid();
            if(textScheduleDetail.getCode()!=ErrorCode.Success.getCode()){
                return ErrorCode.IllegalArument;
            }
            materialsScheduleDetailDO.setId(textScheduleDetail.getValue().toString());
            materialsScheduleDetailDO.setMaterialsScheduleId(textSchedule.getValue().toString());
            materialsScheduleDetailDO.setRealAmount(BigDecimal.ZERO);
            materialsScheduleDetailDO.setStatus(0);
            materialsScheduleDetailDO.setInLocation(materialsScheduleDO.getInLocation());
            if(materialsScheduleDO.getType().equals(1)){
                materialsScheduleDetailDO.setOutLocation(materialsScheduleDO.getOutLocation());
            }
            materialsScheduleDetailMapper.add(materialsScheduleDetailDO);
            if(materialsScheduleAddVO.getHeaderInfo().getType().equals(0)){
                WarehouseInboundDetailVO detail = new WarehouseInboundDetailVO();
                detail.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0, 4));
                detail.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
                detail.setMaterialNo(detailVO.getMaterialsNo());
                detail.setMaterialName(detailVO.getMaterialsDes());
                detail.setMaterialType(detailVO.getMaterialsType());
                detail.setUnit(detailVO.getUnit());
                detail.setAmount(detailVO.getAmount());
                detail.setRealAmount(BigDecimal.ZERO);
                inDetailList.add(detail);
            }else {
                WarehouseDeliveryDetailVO detail=new WarehouseDeliveryDetailVO();
                detail.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0, 4));
                detail.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
                detail.setMaterialNo(detailVO.getMaterialsNo());
                detail.setMaterialName(detailVO.getMaterialsDes());
                detail.setMaterialType(detailVO.getMaterialsType());
                detail.setUnit(detailVO.getUnit());
                detail.setAmount(detailVO.getAmount());
                detail.setRealAmount(BigDecimal.ZERO);
                outDetailList.add(detail);
            }
            num = num.add(detailVO.getAmount());

            //同步到SAP创建预留单
            //// TODO: 2018/4/20 0020  是否要处理sap库区编码
            obligateVO1 = new ObligateVO();
            obligateVO1.setMaterialNo(detailVO.getMaterialsNo());
            obligateVO1.setAmount(detailVO.getAmount());
            obligateVO1.setMoveType(materialsScheduleDO.getSapType());
            if(materialsScheduleDO.getType() == 1){
                obligateVO1.setSapOutArea(materialsScheduleDO.getSapOutArea());
                obligateVO1.setSapInArea(realSapCode);
            }else{
                obligateVO1.setSapOutArea(detailVO.getOutLocation());
                obligateVO1.setSapInArea(realSapCode);
            }
            obligateVOList1.add(obligateVO1);
            obligateVO2 = new ObligateVO();
            BeanUtils.copyProperties(obligateVO1, obligateVO2);
            if(materialsScheduleDO.getType() == 1){
                obligateVO2.setSapInArea(materialsScheduleDO.getInLocation());
                obligateVO2.setSapOutArea(realSapCode);
            }else{
                obligateVO2.setSapInArea(materialsScheduleDO.getSapInArea());
                obligateVO2.setSapOutArea(realSapCode);
            }

            obligateVOList2.add(obligateVO2);
        }
        materialsScheduleMapper.add(materialsScheduleDO);
        if(materialsScheduleAddVO.getHeaderInfo().getType().equals(0)){
            WarehouseInboundVO warehouseInboundVO=new WarehouseInboundVO();
            warehouseInboundVO.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0,4));
            warehouseInboundVO.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
            warehouseInboundVO.setWarehouseCode(materialsScheduleDO.getInLocation());
            warehouseInboundVO.setInArea(materialsScheduleDO.getInArea());
            warehouseInboundVO.setSapInArea(materialsScheduleDO.getSapInArea());
            warehouseInboundVO.setAmount(num);
            warehouseInboundAddVO.setHeaderInfo(warehouseInboundVO);
            warehouseInboundAddVO.setDetailList(inDetailList);
            warehouseInboundService.add(warehouseInboundAddVO,materialsScheduleDO.getCreateId(),orgId);

        }else {
            WarehouseDeliveryVO deliveryVO = new WarehouseDeliveryVO();
            deliveryVO.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0,4));
            deliveryVO.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
            deliveryVO.setWarehouseCode(materialsScheduleDO.getOutLocation());
            deliveryVO.setOutArea(materialsScheduleDO.getOutArea());
            deliveryVO.setSapOutArea(materialsScheduleDO.getSapOutArea());
            deliveryVO.setAmount(num);
            DeliveryAddVO.setHeaderInfo(deliveryVO);
            DeliveryAddVO.setDetailList(outDetailList);
            warehouseDeliveryService.add(DeliveryAddVO,materialsScheduleDO.getCreateId(),orgId);
        }
//        //提供给塔机的服务不自动创建预留单(不是塔机的请求才创建预留单)
//        boolean notTJ = materialsScheduleAddVO.getSapCode() == null || !materialsScheduleAddVO.getSapCode().equals("2130");
//        if(notTJ){
//            //同步到SAP创建预留单
//            ObligateHeaderVO headerVO = new ObligateHeaderVO();
//            headerVO.setBusinesId(materialsScheduleDO.getId());
//            headerVO.setBusinesOrder(materialsScheduleDO.getRequisitionNo());
//            headerVO.setBusinesSingle(materialsScheduleDO.getRequisitionNo().substring(0, 4));
//            sapCommonService.createObligateOrder(headerVO, obligateVOList1, obligateVOList2 , orgId);
//        }

        return ErrorCode.Success;
    }

    /**
     * 移除领料单
     * @param ids
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode remove(List<String> ids) throws Exception{
        for (String id:ids) {
            MaterialsScheduleDO materialsScheduleDO=materialsScheduleMapper.item(id);
            if(materialsScheduleDO==null){
                throw new Exception("参数异常");
            }
            if(!materialsScheduleDO.getStatus().equals(0)){
                throw new Exception("领料单号"+materialsScheduleDO.getRequisitionNo()+"不可删除");
            }
            materialsScheduleMapper.delete(id);
            materialsScheduleDetailMapper.deleteByMainId(id);
            List<String> noList=new ArrayList<>();
            noList.add(materialsScheduleDO.getRequisitionNo());
            if(materialsScheduleDO.getType().equals(0)){
                warehouseInboundService.removeByBusinessOrders(noList,materialsScheduleDO.getOrgId());
            }else {
                warehouseDeliveryService.removeByBusinessOrders(noList,materialsScheduleDO.getOrgId());
            }
        }
        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public synchronized ErrorCode update(MaterialsScheduleAddVO materialsScheduleAddVO, String orgId) throws Exception{
        MaterialsScheduleDO materialsScheduleDO = materialsScheduleMapper.item(materialsScheduleAddVO.getHeaderInfo().getId());
        if(materialsScheduleDO==null){
            return ErrorCode.Failure;
        }
        if(materialsScheduleDO.getStatus().equals(2)){
            return ErrorCode.MaterialsScheduleNotUpDate;
        }
        materialsScheduleDO.setNote(materialsScheduleAddVO.getHeaderInfo().getNote());
        materialsScheduleDO.setSapType(materialsScheduleAddVO.getHeaderInfo().getSapType());
        List<FindMaterialsInfos> infos=new ArrayList<>();
        if(materialsScheduleAddVO.getHeaderInfo().getType().equals(1)){
            for (MaterialsScheduleDetailVO detailVO:materialsScheduleAddVO.getDetailList()) {
                if(detailVO.getStatus()<=1){
                    FindMaterialsInfos findMaterialsInfos=new FindMaterialsInfos();
                    findMaterialsInfos.setMaterialsNo(detailVO.getMaterialsNo());
                    findMaterialsInfos.setAmount(detailVO.getAmount().subtract(detailVO.getRealAmount()));
                    infos.add(findMaterialsInfos);
                }
            }
            FindMaterialsNumParam findMaterialsNumParam=new FindMaterialsNumParam();
            findMaterialsNumParam.setMaterialsNos(infos);
            findMaterialsNumParam.setOrgId(orgId);
            findMaterialsNumParam.setBusinessOrder(materialsScheduleAddVO.getHeaderInfo().getRequisitionNo());
            findMaterialsNumParam.setWarehousCode(materialsScheduleAddVO.getHeaderInfo().getOutLocation());
            if(!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)){
                return ErrorCode.PartMaterialsNotNumber;
            }
        }
        List<String> updateIds = new ArrayList<>();

    /*    if (materialsScheduleAddVO.getDetailList() != null && materialsScheduleAddVO.getDetailList().size() > 0){
            materialsScheduleDO.setInArea(materialsScheduleAddVO.getDetailList().get(0).getInArea());
            materialsScheduleDO.setOutArea(materialsScheduleAddVO.getDetailList().get(0).getOutArea());
        }*/


        for(MaterialsScheduleDetailVO detailVO:materialsScheduleAddVO.getDetailList()) {
            String inLocation = detailVO.getInLocation();
            String outLocation = detailVO.getOutLocation();
            String deliveryNo = detailVO.getDeliveryNo();
            updateIds.add(detailVO.getId());
            MaterialsScheduleDetailDO detailDO = materialsScheduleDetailMapper.selectByPrimaryKey(detailVO.getId());
            if (detailDO == null) {
                throw new Exception("领料单详情有误");
            }
            /*if (detailVO.getAmount().equals(detailDO.getAmount())) {
                continue;
            }*/
            if (detailVO.getAmount().compareTo(detailDO.getRealAmount()) < 0) {
                throw new Exception("零件单号:" + detailDO.getMaterialsNo() + "，出入库已完成无法修改");
            }
            detailDO.setAmount(detailVO.getAmount());
            detailDO.setInLocation(inLocation);
            detailDO.setOutLocation(outLocation);
            detailDO.setDeliveryNo(deliveryNo);
            materialsScheduleDetailMapper.update(detailDO);
            Integer status = detailDO.getStatus();
            if (status.equals(2)) {
                status = 1;
            }
            if (materialsScheduleDO.getType().equals(0)) {
                warehouseInboundService.updateDetailState(materialsScheduleDO.getRequisitionNo(), detailDO.getMaterialsNo(), detailVO.getAmount(), status, orgId);
            } else {
                warehouseDeliveryService.updateDetailState(materialsScheduleDO.getRequisitionNo(), detailDO.getMaterialsNo(), detailVO.getAmount(), status, orgId);
            }
        }

        //删除详情信息
        updateDeleteDetails(materialsScheduleAddVO,updateIds);

        if(materialsScheduleDO.getType().equals(0)){
            warehouseInboundService.updateState(materialsScheduleDO.getRequisitionNo(),materialsScheduleDO.getStatus(), orgId);
        }else{
            warehouseDeliveryService.updateState(materialsScheduleDO.getRequisitionNo(),materialsScheduleDO.getStatus(), orgId);
        }
        //需要审核流程的公司在在编辑领料单的时候需要重置审核状态
        resetAuditInfo(orgId,materialsScheduleDO);
        materialsScheduleMapper.update4Edit(materialsScheduleDO);
        return ErrorCode.Success;
    }

    private void resetAuditInfo(String orgId, MaterialsScheduleDO oldMaterialsScheduleDO) {
        //如果发运交接单老的审核状态是审核通过的则不重置审核信息
        Integer auditStatus = oldMaterialsScheduleDO.getAuditStatus();
        if(auditStatus != null && auditStatus.compareTo(MaterialsScheduleAuditStatusEnum.AUDIT_PASS.getAuditStatus()) == 0){
            return ;
        }
        if(auditStatus != null && auditStatus.compareTo(MaterialsScheduleAuditStatusEnum.AUDIT_REJECT.getAuditStatus()) == 0){
            //查看公司是否需要有审核流程
            boolean deliveryReceiptAuditSetting = systemParameterService.getDeliveryReceiptAuditSetting(orgId);
            if(deliveryReceiptAuditSetting){
                oldMaterialsScheduleDO.setAuditUserName(null);
                oldMaterialsScheduleDO.setAuditUserId(null);
                oldMaterialsScheduleDO.setAuditDate(null);
                oldMaterialsScheduleDO.setAuditOpinion(null);
                oldMaterialsScheduleDO.setAuditStatus(MaterialsScheduleAuditStatusEnum.AUDIT_WAIT.getAuditStatus());
            }
        }
    }

    private void updateDeleteDetails(MaterialsScheduleAddVO materialsScheduleAddVO,List<String> updateIds) throws Exception {
        String mainId = materialsScheduleAddVO.getHeaderInfo().getId();
        MaterialsScheduleVO headerInfo = materialsScheduleAddVO.getHeaderInfo();
        List<MaterialsScheduleDetailDO> list = materialsScheduleDetailMapper.list(mainId);
        List<MaterialsScheduleDetailDO> deleteList = list.stream().filter(x->!updateIds.contains(x.getId())).collect(Collectors.toList());
        if (null == deleteList || deleteList.isEmpty()){
             return;
        }
        boolean success;
        for (MaterialsScheduleDetailDO detailDO: deleteList) {
            if (detailDO == null) {
                throw new Exception("领料单详情有误");
            }

            Integer status = detailDO.getStatus();
            if (0 != status) {
                throw new Exception("零件号:" + detailDO.getMaterialsNo() + "已经出库不允许删除");
            }
            //删除领料单详情表
            success = materialsScheduleDetailMapper.delete(detailDO.getId()) > 0;
            if (!success) {
                throw new Exception("零件号:" + detailDO.getMaterialsNo() + "删除失败");
            }
            //删除出库事务表明细
            if (headerInfo.getType().equals(0)){
                WarehouseInboundDetailDO warehouseInboundDetailDO = new WarehouseInboundDetailDO();
                warehouseInboundDetailDO.setBusinessOrder(materialsScheduleAddVO.getHeaderInfo().getRequisitionNo());
                warehouseInboundDetailDO.setOrgId(materialsScheduleAddVO.getHeaderInfo().getOrgId());
                warehouseInboundDetailDO.setMaterialNo(detailDO.getMaterialsNo());
                warehouseInboundDetailMapper.deleteByMaterial(warehouseInboundDetailDO);
            }else {
                WarehouseDeliveryDetailDO warehouseDeliveryDetailDO = new WarehouseDeliveryDetailDO();
                warehouseDeliveryDetailDO.setBusinessOrder(materialsScheduleAddVO.getHeaderInfo().getRequisitionNo());
                warehouseDeliveryDetailDO.setOrgId(materialsScheduleAddVO.getHeaderInfo().getOrgId());
                warehouseDeliveryDetailDO.setMaterialNo(detailDO.getMaterialsNo());
                warehouseDeliveryDetailMapper.deleteByMaterial(warehouseDeliveryDetailDO);
            }
        }

    }

    public PageCommonVO list(SearchCommonVO<MaterialsScheduleVO> condition) {
        PageCommonVO result = new PageCommonVO();
        if (StringUtils.isEmpty(condition.getSort())) {
            condition.setSort("create_date desc");
        }
        MaterialsScheduleVO filter = fillRequisitionNoList(condition.getFilters());

        PageHelperPlus.orderBy(condition.getSort());
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<MaterialsScheduleDO> doList = materialsScheduleMapper.list(filter);
        List<MaterialsScheduleVO> voList = new ArrayList<>();
        for (MaterialsScheduleDO entity : doList) {
            MaterialsScheduleVO model = new MaterialsScheduleVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    /**
     * 支持多单号搜索
     *
     * @param filter
     * @return
     */
    private MaterialsScheduleVO fillRequisitionNoList(MaterialsScheduleVO filter) {
        if (StringUtils.isNotBlank(filter.getRequisitionNo())) {
            List<String> requisitionNoList = xcmg.device.infra.StringUtil.getStrSplitList(filter.getRequisitionNo());
            if (requisitionNoList.size() > 1) {
                filter.setRequisitionNoList(requisitionNoList);
                filter.setRequisitionNo(null);
            }
        }
        return filter;
    }

    public MaterialsScheduleAddVO item(String MaterialsScheduleId){
        MaterialsScheduleAddVO result = new MaterialsScheduleAddVO();
        MaterialsScheduleDO materialsScheduleDO = materialsScheduleMapper.item(MaterialsScheduleId);
        MaterialsScheduleVO materialsScheduleVO = new MaterialsScheduleVO();
        BeanUtils.copyProperties(materialsScheduleDO,materialsScheduleVO);
        if(materialsScheduleDO == null){
            return result;
        }
        result.setHeaderInfo(materialsScheduleVO);
        List<MaterialsScheduleDetailVO> listVO = new ArrayList<>();
        List<MaterialsScheduleDetailDO> listDO = materialsScheduleDetailMapper.listForLocationUser(MaterialsScheduleId);
        for(MaterialsScheduleDetailDO entity:listDO){
            MaterialsScheduleDetailVO model = new MaterialsScheduleDetailVO();
            BeanUtils.copyProperties(entity,model);
            model.setInArea(materialsScheduleDO.getInArea());
            model.setOutArea(materialsScheduleDO.getOutArea());
            model.setSapInArea(materialsScheduleDO.getSapInArea());
            model.setSapOutArea(materialsScheduleDO.getSapOutArea());
            if (StringUtils.isNotBlank(model.getStockLocation())){
                model.setLocationDesc(warehouseAreaLocationDOMapper.getLocationDesc(model.getStockLocation()));
            }
            listVO.add(model);
        }
        result.setDetailList(listVO);
        return result;
    }

    public List<MaterialsScheduleAddVO> itemGroupByArea(String materialsScheduleId) {
        List<MaterialsScheduleAddVO> list=new ArrayList<>();

        MaterialsScheduleDO materialsScheduleDO = materialsScheduleMapper.item(materialsScheduleId);
        if(null==materialsScheduleDO){
            return list;
        }
        //按领入库区分组
        Map<String,List<MaterialsScheduleDetailVO>> materialsScheduleDetailVOMapByArea=new HashMap<>();
        List<MaterialsScheduleDetailDO> listDO = materialsScheduleDetailMapper.listForLocationUser(materialsScheduleId);
        for(MaterialsScheduleDetailDO entity:listDO){
            List<MaterialsScheduleDetailVO> listVO=materialsScheduleDetailVOMapByArea.get(entity.getOutLocation());
            if(CollectionUtils.isEmpty(listVO)){
                listVO=new ArrayList<>();
            }
            MaterialsScheduleDetailVO model = new MaterialsScheduleDetailVO();
            BeanUtils.copyProperties(entity,model);
            model.setInArea(materialsScheduleDO.getInArea());
            model.setOutArea(materialsScheduleDO.getOutArea());
            model.setSapInArea(materialsScheduleDO.getSapInArea());
            model.setSapOutArea(materialsScheduleDO.getSapOutArea());
            if (StringUtils.isNotBlank(model.getStockLocation())){
                model.setLocationDesc(warehouseAreaLocationDOMapper.getLocationDesc(model.getStockLocation()));
            }
            listVO.add(model);
            materialsScheduleDetailVOMapByArea.put(entity.getOutLocation(),listVO);
        }

        for(Map.Entry<String,List<MaterialsScheduleDetailVO>> en:materialsScheduleDetailVOMapByArea.entrySet()){
            List<MaterialsScheduleDetailVO> groupDetailList=en.getValue();
            MaterialsScheduleAddVO materialsScheduleAddVO = new MaterialsScheduleAddVO();
            MaterialsScheduleVO materialsScheduleVO = new MaterialsScheduleVO();
            BeanUtils.copyProperties(materialsScheduleDO,materialsScheduleVO);
            materialsScheduleAddVO.setHeaderInfo(materialsScheduleVO);
            materialsScheduleAddVO.setDetailList(groupDetailList);
            list.add(materialsScheduleAddVO);
        }
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean updateByInbound(String billNo, String materialNo, BigDecimal realAmount,
                                   Integer singelState, Integer totalState, String orgId)throws Exception{
        MaterialsScheduleDO inboundDO = materialsScheduleMapper.findByBillNo(billNo, orgId);
        if(inboundDO == null){
            return false;
        }
        MaterialsScheduleDetailDO detailDO = materialsScheduleDetailMapper.findByOrderAndMaterialNo(inboundDO.getId(), materialNo);
        if(detailDO == null){
            return false;
        }
        if (realAmount.compareTo(detailDO.getAmount()) > 0) {
            throw new Exception("实际入库数量不能大于领料量");
        }
        BigDecimal nowAmount = realAmount;
        if (detailDO.getRealAmount() != null) {
            nowAmount = realAmount.subtract(detailDO.getRealAmount());
        }
        detailDO.setRealAmount(realAmount);
        detailDO.setStatus(singelState);
        boolean success = materialsScheduleDetailMapper.update(detailDO) > 0;

//        LogHelper.monitor("是否塔机用户" + companyUtil.isTJ(orgId));
//        //领料单入库，同步crm
//        if (companyUtil.isTJ(orgId)) { //塔机用户才同步crm
//            Map resultMap = syncCrm(billNo, materialNo, realAmount, inboundDO);
//            boolean isSuccess = true;
//
//            //syncCrmFlag为null，为未同步
//            if (!StringUtils.isNotEmpty(inboundDO.getSyncCrmFlag())){
//               inboundDO.setSyncCrmFlag("0");
//            }
//
//            //同步失败需要回写
//            if (resultMap.get("Flag") != null && resultMap.get("Flag").equals(false)){
//                String msg = inboundDO.getSyncCrmMsg() == null ? "" : inboundDO.getSyncCrmMsg();
//                msg += resultMap.get("Msg").toString() + ";";
//                inboundDO.setSyncCrmFlag("2");
//                inboundDO.setSyncCrmMsg(msg);
//                isSuccess = false;
//            }
//
//            //本次成功并且之前没有失败的记录，则回写成功
//            if (isSuccess && !inboundDO.getSyncCrmFlag().equals("2")){
//                inboundDO.setSyncCrmFlag("1");
//                inboundDO.setSyncCrmMsg("操作成功");
//            }
//        }

        if (success) {
            //更新采购入库单记录
            inboundDO.setStatus(totalState);

            success = materialsScheduleMapper.update(inboundDO) > 0;
            if (!success) {
                return false;
            }
        }
        return success;
    }

//    private Map syncCrm(String billNo, String materialNo, BigDecimal realAmount, MaterialsScheduleDO inboundDO) {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        RegionAllotCrmDO regionAllotCrmDO = new RegionAllotCrmDO();
//        regionAllotCrmDO.setCode(materialNo);
//        regionAllotCrmDO.setReceiveQty(realAmount.toString());
//        regionAllotCrmDO.setReceiveTime(sdf.format(new Date()));
//        regionAllotCrmDO.setStatus(ConstantInfo.CRM_STATUS_RECEIVE);
//        regionAllotCrmDO.setPmsCode(billNo);
//        List<RegionAllotCrmDO> regionAllotCrmDOList = new ArrayList<>();
//        regionAllotCrmDOList.add(regionAllotCrmDO);
//        Map<String, List<RegionAllotCrmDO>> paramMap = new HashMap<>();
//        paramMap.put("DeliveryReceiptlist", regionAllotCrmDOList);
//        logger.info("领料单入库,同步crm发货签收,请求入参{}", JsonUtil.objectToString(paramMap));
//        Map resultMap = crmClient.syncPartsApply(paramMap);
//        logger.info("领料单入库,同步crm发货签收,返回结果{}", JsonUtil.objectToString(resultMap));
//
//        return resultMap;
//    }

    //导出
    private void invokeExport(List<MaterialsScheduleVO> voList) throws Exception {
        String title = "领料单导出";
        String[] rowsName = new String[]{"序号", "领料单号", "单据类型", "制单部门", "创建人", "制单时间", "领出仓库",
                "领入仓库", "移动类型", "SAP领入预留单号", "SAP领出预留单号", "出入库状态", "零件编码", "零件名称", "分类", "单位", "领料数量", "出入库数量", "CRM单号", "领出过账状态", "领入过账状态", "发货通知单号"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs = null;
        for (int i = 0; i < voList.size(); i++) {
            MaterialsScheduleVO e = voList.get(i);
            List<MaterialsScheduleDetailDO> detailList = materialsScheduleDetailMapper.list(e.getId());
            for(MaterialsScheduleDetailDO detailDO : detailList){
                objs = new Object[rowsName.length];
                objs[0] = i+1;
                objs[1] =e.getRequisitionNo();
                objs[2] = e.getType()==0?"从生产领料":"从备件领料";
                objs[3] = e.getCreatePartName();
                objs[4] = e.getCreateName();
                objs[5]= e.getCreateDate()==null?"": DateUtil.formatDateTime(e.getCreateDate());
                objs[6]=detailDO.getOutLocation();
                objs[7]=detailDO.getInLocation();
                objs[8]=e.getSapType();
                objs[9]=e.getSapInCode();
                objs[10]=e.getSapOutCode();
                objs[11]=getStatusDesc(e.getStatus().toString(),e.getType());
                objs[12]=detailDO.getMaterialsNo();
                objs[13]=detailDO.getMaterialsDes();
                objs[14]=detailDO.getMaterialsType();
                objs[15]=detailDO.getUnit();
                objs[16]=detailDO.getAmount();
                objs[17]=detailDO.getRealAmount();
                objs[18]=e.getCrmOrder();
                Integer postOutStatus = detailDO.getPostOutStatus();
                String postOutStatusDes = (postOutStatus == null || postOutStatus.compareTo(0) <= 0) ? "未过账" :
                        postOutStatus.compareTo(1) == 0 ? "部分过账" : "已过账";
                Integer postInStatus = detailDO.getPostInStatus();
                String postInStatusDes = (postInStatus == null || postInStatus.compareTo(0) <= 0) ? "未过账" :
                        postInStatus.compareTo(1) == 0 ? "部分过账" : "已过账";
                objs[19]=postOutStatusDes;
                objs[20]=postInStatusDes;
                objs[21]=detailDO.getDeliveryNo();
                dataList.add(objs);
            }
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getStatusDesc(String statusId,Integer type){
        if (type==null){
            return"";
        }
        if(type==0){
            switch(statusId){
                case "0":
                default:
                    return "未入库";
                case "1":
                    return "部分入库";
                case "2":
                    return "已入库";
                case "3":
                    return "强制结单";
            }
        }else{
            switch(statusId){
                case "0":
                default:
                    return "未出库";
                case "1":
                    return "部分出库";
                case "2":
                    return "已出库";
                case "3":
                    return "强制结单";
            }
        }

    }

    public void export(List<String> scheduleIds) throws Exception{
        List<MaterialsScheduleVO> voList=new ArrayList<>();
        for(String scheduleId:scheduleIds){
            MaterialsScheduleDO entity=materialsScheduleMapper.item(scheduleId);
            MaterialsScheduleVO model=new MaterialsScheduleVO();
            BeanUtils.copyProperties(entity,model);
            if(model!=null){
                voList.add(model);
            }
        }
        invokeExport(voList);
    }

    public void exportAll(MaterialsScheduleVO condition) throws Exception{
        //PageHelperPlus.startPage(0, 0, "create_date desc");
        List<MaterialsScheduleVO> voList=new ArrayList<>();
        List<MaterialsScheduleDO> doList = materialsScheduleMapper.list(condition);
        for (MaterialsScheduleDO entity:doList) {
            MaterialsScheduleVO model=new MaterialsScheduleVO();
            BeanUtils.copyProperties(entity,model);
            voList.add(model);
        }
        invokeExport(voList);
    }

    public FunctionResult importExcel(InputStream in, String orgId,Integer type) throws Exception{
        FunctionResult result=new FunctionResult();
        HSSFWorkbook wb=new HSSFWorkbook(in);
        HSSFSheet sheet=wb.getSheetAt(0);

        int totalRow=sheet.getLastRowNum();
        if(totalRow<2){
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        int totalCell=sheet.getRow(1).getLastCellNum();
        if(type.equals(1)&&totalCell!=5){
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }else if(type.equals(0)&&totalCell!=6){
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        List<MaterialsScheduleDetailVO> detailVOList=new ArrayList<>();
        List<MaterialsScheduleDetailVO> errorDetailVOList=new ArrayList<>();
        for(int i=2;i<=totalRow;i++){
            HSSFRow curRow=sheet.getRow(i);
            MaterialsScheduleDetailVO detailVO=new MaterialsScheduleDetailVO();
            if(curRow==null){
                continue;
            }
            curRow.getCell(1).setCellType(1);
            String materialsNo= curRow.getCell(1)==null?"": ExcelUtil.getCellStringValue(curRow.getCell(1));
            String qty=curRow.getCell(4)==null?"1":ExcelUtil.getCellStringValue(curRow.getCell(4));
            if(StringUtil.isNullOrEmpty(qty)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("入库数量不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(!isInteger(qty) || "0".equals(qty)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("入库数量格式不正确");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(new BigDecimal(qty).compareTo(BigDecimal.valueOf(99999999.99)) > 0){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("入库数量过大");
                errorDetailVOList.add(detailVO);
                continue;
            }
            MaterialsVO materialsVO=materialsService.itemByNo(materialsNo,orgId);
            if(materialsVO==null){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("零件不存在");
                errorDetailVOList.add(detailVO);
                continue;
            }
            BigDecimal intQty = new BigDecimal((qty));
            BigDecimal max = new BigDecimal(99999999.99);
            if(intQty.compareTo(max) > 0){
                intQty = max;
            }
            if(type.equals(0)){
                String outLocation= curRow.getCell(5)==null?"": ExcelUtil.getCellStringValue(curRow.getCell(5));
                detailVO.setOutLocation(outLocation);
            }
            detailVO.setAmount(intQty);
            detailVO.setMaterialsNo(materialsVO.getMaterialsNo());
            detailVO.setMaterialsDes(materialsVO.getMaterialsDes());
            detailVO.setMaterialsType(materialsVO.getMaterialsType());
            detailVO.setUnit(materialsVO.getUnit());
            detailVOList.add(detailVO);
        }

        if(ListUtil.isNullOrEmpty(errorDetailVOList)){
            result.setValue(deRepeat(detailVOList));
            result.setCode(ErrorCode.Success);
        }
        else {
            result.setValue(errorDetailVOList);
            result.setCode(ErrorCode.IllegalArument);
        }
        return result;
    }

    private boolean isInteger(String str) {
        if (null == str || "".equals(str)) {
            return false;
        }
        try {
            BigDecimal decimal = new BigDecimal(str);
        }catch (Exception e){
            return false;
        }
        return true;
    }

    public static List<MaterialsScheduleDetailVO> deRepeat(List<MaterialsScheduleDetailVO> repeatList) {
        if(CollectionUtils.isEmpty(repeatList)){
            return repeatList;
        }

        for  ( int i  = 0 ; i< repeatList.size()-1;i++){
            BigDecimal sum =repeatList.get(i).getAmount();
            for  ( int j=repeatList.size()-1;j>i;j -- )  {
                if  (repeatList.get(j).equals(repeatList.get(i))||repeatList.get(j).getMaterialsNo().equals(repeatList.get(i).getMaterialsNo())){
                    sum=sum.add(repeatList.get(j).getAmount());
                    repeatList.remove(j);
                }
            }
            repeatList.get(i).setAmount(sum);
        }
        return repeatList;

    }

    public void download(Integer type) throws Exception{
        if(type.equals(0)){
            FileUtil.downLoadFile(response,filePath,templateInExcelFileName);
        }else {
            FileUtil.downLoadFile(response,filePath,templateOutExcelFileName);
        }
    }

    /**
     * 出库状态：手动完成
     */
    private static final Integer OUT_STATUS_FINISH = 3;

    /**
     * 过账状态。2已过账
     */
    private static final Integer POST_STATUS_YES = 2;

    /**
     * 手动完成单据<br>
     *     materialsNo 不为null,则更改该单据下的零件状态为“手动完成”状态；如果materialsNo为空，则更改整个单据为“手动完成”状态<br>
     *         领料单出库和入库分开，但是表中只有一个出库状态
     * @param billNo  String 单据编号
     * @param materialsNo String 零件编号
     * @param orgId String 企业ID
     * @param type 操作类型（0入库操作，1出库操作）
     * @return ErrorCode 返回码
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode manualFinish(String billNo,String materialsNo,String orgId,int type)
    {
        MaterialsScheduleDO materialsScheduleDO = materialsScheduleMapper.findByBillNo(billNo,orgId);

        if (StringUtil.isNullOrEmpty(materialsNo))//零件编码为空，更新单据状态为“手动完成”
        {
            if (0 == type)//入库操作
            {
                materialsScheduleDO.setPostStatus(POST_STATUS_YES);
                materialsScheduleDO.setStatus(OUT_STATUS_FINISH);
                materialsScheduleMapper.update(materialsScheduleDO);

                warehouseInboundService.updateState(billNo, 3, orgId);

                materialsScheduleDetailMapper.updateInStatus(3, materialsScheduleDO.getId(), null);
                warehouseInboundDetailMapper.updateAllStatus(3, materialsScheduleDO.getRequisitionNo(), orgId);
            }
            else  //出库操作
            {
                materialsScheduleMapper.updateOutStatus(3, billNo);
                warehouseDeliveryService.updateState(billNo, 3, orgId);

                materialsScheduleDetailMapper.updateOutStatus(3, materialsScheduleDO.getId(), null);
                warehouseDeliveryDetailMapper.updateAllStatus(3, materialsScheduleDO.getRequisitionNo(), orgId);
            }
        }
        else
        {
            if (0 == type)//入库操作
            {
                materialsScheduleDetailMapper.updateInStatus(3, materialsScheduleDO.getId(), materialsNo);
                warehouseInboundService.updateDetailState(billNo, materialsNo, null, 3, orgId);
                ErrorCode errorCode = checkBillFinished(materialsScheduleDO.getId(), orgId,type,billNo);

                if (ErrorCode.Success != errorCode)
                {
                    return errorCode;
                }
            }
            else
            {
                materialsScheduleDetailMapper.updateOutStatus(3, materialsScheduleDO.getId(), materialsNo);
                warehouseDeliveryService.updateDetailState(billNo, materialsNo, null, 3, orgId);
                ErrorCode errorCode = checkBillFinished(materialsScheduleDO.getId(), orgId,type,billNo);

                if (ErrorCode.Success != errorCode)
                {
                    return errorCode;
                }
            }
        }
        return ErrorCode.Success;
    }

    /**
     * 校验单据是否已完成<br>
     *     判断单据下的所有零件是否已经完成，如果都完成，则更改单据状态为完成
     * @param billId String
     * @param orgId String
     * @param type 操作类型（0入库操作，1出库操作）
     * @param billNo String
     * @return Boolean
     */
    private ErrorCode checkBillFinished(String billId,String orgId,int type,String billNo)
    {
        boolean flag = true;
        List<MaterialsScheduleDetailDO> detailDOs = materialsScheduleDetailMapper.list(billId);

        if (0 == type)
        {
            for (MaterialsScheduleDetailDO temp : detailDOs)
            {
                if (2==temp.getStatus() || 3==temp.getStatus())
                {
                    //完成状态
                    continue;
                }
                flag = false;
            }
            if (flag)
            {
                materialsScheduleMapper.updateInStatus(3, billNo);
                warehouseInboundService.updateState(billNo, 3, orgId);
            }
        }
        else
        {
            for (MaterialsScheduleDetailDO temp : detailDOs)
            {
                if (2==temp.getStatus() || 3==temp.getStatus())
                {
                    //完成状态
                    continue;
                }
                flag = false;
            }
            if (flag)
            {
                materialsScheduleMapper.updateOutStatus(3, billNo);
                warehouseDeliveryService.updateState(billNo, 3, orgId);
            }
        }

        return ErrorCode.Success;
    }

    /**
     * 获取需要过账的领料单
     *
     * @param orgId
     * @param inOutCode 0：领入过账，1：领出过账
     * @return
     */
    public List<MaterialsScheduleDO> listNeedSapPostingByOrg(String orgId, Integer inOutCode) {

        if (ObligateVO.OUT_SAP.equals(inOutCode)) {
            return materialsScheduleMapper.listOut4SapPosting(orgId);
        }
        return materialsScheduleMapper.listIn4SapPosting(orgId);
    }

    public ErrorCode receiptConfirm(String id, String userName) {
        MaterialsScheduleDO record = new MaterialsScheduleDO();
        record.setId(id);
        record.setIsReceipt(1);
        record.setReceiptUser(userName);
        record.setReceiptDate(new Date());
        return materialsScheduleMapper.update(record) > 0 ? ErrorCode.Success : ErrorCode.Failure;
    }

//    public SapStockVO sapStock(String materialsNo, String orgId) throws Exception {
//        String sapCode = companyInfoMapper.getSapCodeByOrgId(orgId);
//        if (org.apache.commons.lang3.StringUtils.isBlank(sapCode) || !CompanyUtil.isJC(sapCode)) {
//            return null;
//        }
//        ImportParam importParam = new ImportParam();
//        importParam.setFunction("ZPMS_BJ_GET_STOCK");
//        Map<String, String> map = new HashMap<>();
//        map.put("WERKS", sapCode);
//        importParam.setCommonParamMap(map);
//        Map<String, List<Map<String, String>>> tableParamMap = new HashMap<>();
//        List<Map<String, String>> list = new ArrayList<>();
//        Map<String, String> mapd = new HashMap<>();
//        mapd.put("MATNR", materialsNo);
//        list.add(mapd);
//        tableParamMap.put("MATNR", list);
//        importParam.setTableParamMap(tableParamMap);
//        importParam.setTable("STOCK");
//        importParam.setSapCode(sapCode);
//        LogHelper.monitor("========调用大厂库存查询接口开始========");
//        OutputParam outputParam = SAPCommonUtil.getData(importParam);
//        LogHelper.monitor("========调用大厂库存查询接口结束========");
//
//        if (null == outputParam || outputParam.getCode() != 0 || ListUtil.isNullOrEmpty(outputParam.getDataList())) {
//            //sap返回错误的时候，前端直接不显示
//            return null;
//        }
//        return fillResult(outputParam, materialsNo);
//    }
//
//    private SapStockVO fillResult(OutputParam outputParam, String materialsNo) throws Exception {
//        SapStockVO sapStockVO = null;
//        if ("OK".equals(outputParam.getDataHeader().get("RETURNCODE"))) {
//            sapStockVO = new SapStockVO();
//            List<SapStockDetailVO> details = new ArrayList<>();
//            BigDecimal totalStock = BigDecimal.ZERO;
//            List<Map<String, String>> result = outputParam.getDataList();
//            for (Map<String, String> mapResult : result) {
//                SapStockDetailVO detailVO = new SapStockDetailVO();
//                detailVO.setSapArea(mapResult.get("LGORT"));
//                BigDecimal areaStock = new BigDecimal(mapResult.get("LABST"));
//                detailVO.setStock(areaStock);
//                details.add(detailVO);
//                totalStock = totalStock.add(areaStock);
//            }
//            sapStockVO.setMaterialsNo(materialsNo);
//            sapStockVO.setDetailVOList(details);
//            sapStockVO.setTotalStock(totalStock);
//        } else {
//            throw new Exception("查询大厂库存出错");
//        }
//
//        return sapStockVO;
//    }

    /**
     * 调整领料单
     *
     * @param materialsScheduleAddVO
     * @param orgId
     * @throws Exception
     */
    public void adjust(MaterialsScheduleAddVO materialsScheduleAddVO, String orgId)
            throws Exception {
        MaterialsScheduleDO scheduleDO = materialsScheduleMapper.item(materialsScheduleAddVO.getHeaderInfo().getId());
        if (null == scheduleDO || !orgId.equals(scheduleDO.getOrgId())) {
            throw new Exception("单据不存在");
        }
        if (STATUS_FINISH.equals(scheduleDO.getStatus()) || STATUS_END.equals(scheduleDO.getStatus())) {
            throw new Exception("出入库完成状态或者结单状态不允许调整");
        }
        List<MaterialsScheduleDetailVO> detailVOS = materialsScheduleAddVO.getDetailList();
        for (MaterialsScheduleDetailVO detailVO :  detailVOS) {
            MaterialsScheduleDetailDO detailDO = materialsScheduleDetailMapper.selectByPrimaryKey(detailVO.getId());
            if (null == detailDO) {
                throw new Exception("该行数据不存在");
            }
            if (detailVO.getAmount().compareTo(detailDO.getRealAmount()) < 0) {
                throw new Exception("领料数量不能小于实际数量");
            }
            detailDO.setId(detailVO.getId());
            //领料数量
            detailDO.setAmount(detailVO.getAmount());
            if (!detailDO.isNotOutStock() && !detailVO.getOutLocation().equals(detailDO.getOutLocation())) {
                throw new Exception("领出仓库只能在本行处于未出库状态进行修改");
            }
            detailDO.setOutLocation(detailVO.getOutLocation());
            materialsScheduleDetailMapper.update(detailDO);
            //copy update方法中的入库事务单代码
            Integer status=detailDO.getStatus();
            if(status.equals(2)){
                status=1;
            }
            //copy update方法,0 备件从生产，更新入库事务单，1生产从备件，更新T_WAREHOUSE_DELIVERY_DETAIL
            if(scheduleDO.getType().equals(0)){
                warehouseInboundService.updateDetailState(scheduleDO.getRequisitionNo(),detailDO.getMaterialsNo(),detailVO.getAmount(),status, orgId);
            }else {
                warehouseDeliveryService.updateDetailState(scheduleDO.getRequisitionNo(),detailDO.getMaterialsNo(),detailVO.getAmount(),status, orgId);
            }
        }
        if(scheduleDO.getType().equals(0)){
            warehouseInboundService.updateState(scheduleDO.getRequisitionNo(),scheduleDO.getStatus(), orgId);
        }else{
            warehouseDeliveryService.updateState(scheduleDO.getRequisitionNo(),scheduleDO.getStatus(), orgId);
        }
    }

    private static final String TJ_DEFAULT_WAREHOUSE_CODE = "CC00";
    /**
     * 外部接口新增领料单,分开以便业务不同调整方便
     * @param materialsScheduleAddVO
     * @param orgId
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public String add4External(MaterialsScheduleAddVO materialsScheduleAddVO,String orgId) throws Exception{

        String realSapCode = TJ_DEFAULT_WAREHOUSE_CODE;
        DataDictionaryDO dictionaryDO = dataDictionaryMapper.itemByCode(CompanyConstants.MID_WAREHOUSE_CODE, orgId);
        if (null != dictionaryDO && StringUtils.isNotBlank(dictionaryDO.getName())) {
            realSapCode = dictionaryDO.getName();
        }

        //领料主表
        MaterialsScheduleDO materialsScheduleDO = new MaterialsScheduleDO();
        BeanUtils.copyProperties(materialsScheduleAddVO.getHeaderInfo(),materialsScheduleDO);
        ActionResult<String> textSchedule = fastGenClient.textGuid();
        if (textSchedule.getCode() != ErrorCode.Success.getCode()) {
            throw new Exception("生成ID错误");
        }
        materialsScheduleDO.setId(textSchedule.getValue());
        materialsScheduleDO.setOrgId(orgId);
        String ordNo = genDocumentService.genDocumentNo(BillDesc.MaterialsCode, orgId);
        materialsScheduleDO.setRequisitionNo(ordNo);
        if (null == materialsScheduleDO.getType()) {
            throw new Exception("请传入领料类型");
        }
        if(materialsScheduleDO.getType().equals(0)){
            materialsScheduleDO.setDocumentName("从生产领料");
        }else {
            materialsScheduleDO.setDocumentName("从备件领料");
        }
        materialsScheduleDO.setStatus(0);
        materialsScheduleDO.setAuditStatus(0);
        WarehouseInboundAddVO warehouseInboundAddVO=new WarehouseInboundAddVO();
        WarehouseDeliveryAddVO DeliveryAddVO = new WarehouseDeliveryAddVO();

        List<WarehouseInboundDetailVO> inDetailList = new ArrayList<>();
        List<WarehouseDeliveryDetailVO> outDetailList = new ArrayList<>();
        //领料详情表
        BigDecimal num = BigDecimal.ZERO;
        //生成区域调拨详情记录

        /*List<ObligateVO> obligateVOList1 = new ArrayList<>();
        List<ObligateVO> obligateVOList2 = new ArrayList<>();
        ObligateVO obligateVO1;
        ObligateVO obligateVO2;*/
        List<FindMaterialsInfos> infos=new ArrayList<>();
        if(materialsScheduleAddVO.getHeaderInfo().getType().equals(1)){
            for (MaterialsScheduleDetailVO detailVO:materialsScheduleAddVO.getDetailList()) {
                FindMaterialsInfos findMaterialsInfos=new FindMaterialsInfos();
                findMaterialsInfos.setMaterialsNo(detailVO.getMaterialsNo());
                findMaterialsInfos.setAmount(detailVO.getAmount());
                infos.add(findMaterialsInfos);
            }
            FindMaterialsNumParam findMaterialsNumParam=new FindMaterialsNumParam();
            findMaterialsNumParam.setMaterialsNos(infos);
            findMaterialsNumParam.setOrgId(orgId);

            findMaterialsNumParam.setWarehousCode(materialsScheduleAddVO.getHeaderInfo().getOutLocation());
            if(!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)){
                throw new Exception("部分零件库存不足");
            }
        }

        for(MaterialsScheduleDetailVO detailVO:materialsScheduleAddVO.getDetailList()){
            MaterialsScheduleDetailDO materialsScheduleDetailDO = new MaterialsScheduleDetailDO();
            BeanUtils.copyProperties(detailVO,materialsScheduleDetailDO);
            ActionResult<String> textScheduleDetail=fastGenClient.textGuid();
            if(textScheduleDetail.getCode()!=ErrorCode.Success.getCode()){
                throw new Exception("ID生成错误");
            }
            materialsScheduleDetailDO.setId(textScheduleDetail.getValue().toString());
            materialsScheduleDetailDO.setMaterialsScheduleId(textSchedule.getValue().toString());
            materialsScheduleDetailDO.setRealAmount(BigDecimal.ZERO);
            materialsScheduleDetailDO.setStatus(0);
            materialsScheduleDetailDO.setInLocation(materialsScheduleDO.getInLocation());
            if(materialsScheduleDO.getType().equals(1)){
                materialsScheduleDetailDO.setOutLocation(materialsScheduleDO.getOutLocation());
            }
            materialsScheduleDetailMapper.add(materialsScheduleDetailDO);
            if(materialsScheduleAddVO.getHeaderInfo().getType().equals(0)){
                WarehouseInboundDetailVO detail = new WarehouseInboundDetailVO();
                detail.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0, 4));
                detail.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
                detail.setMaterialNo(detailVO.getMaterialsNo());
                detail.setMaterialName(detailVO.getMaterialsDes());
                detail.setMaterialType(detailVO.getMaterialsType());
                detail.setUnit(detailVO.getUnit());
                detail.setAmount(detailVO.getAmount());
                detail.setRealAmount(BigDecimal.ZERO);
                inDetailList.add(detail);
            }else {
                WarehouseDeliveryDetailVO detail=new WarehouseDeliveryDetailVO();
                detail.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0, 4));
                detail.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
                detail.setMaterialNo(detailVO.getMaterialsNo());
                detail.setMaterialName(detailVO.getMaterialsDes());
                detail.setMaterialType(detailVO.getMaterialsType());
                detail.setUnit(detailVO.getUnit());
                detail.setAmount(detailVO.getAmount());
                detail.setRealAmount(BigDecimal.ZERO);
                outDetailList.add(detail);
            }
            num = num.add(detailVO.getAmount());

            //同步到SAP创建预留单
            //// TODO: 2018/4/20 0020  是否要处理sap库区编码
            /*obligateVO1 = new ObligateVO();
            obligateVO1.setMaterialNo(detailVO.getMaterialsNo());
            obligateVO1.setAmount(detailVO.getAmount());
            obligateVO1.setMoveType(materialsScheduleDO.getSapType());
            if(materialsScheduleDO.getType() == 1){
                obligateVO1.setSapOutArea(materialsScheduleDO.getSapOutArea());
                obligateVO1.setSapInArea(realSapCode);
            }else{
                obligateVO1.setSapOutArea(detailVO.getOutLocation());
                obligateVO1.setSapInArea(realSapCode);
            }
            obligateVOList1.add(obligateVO1);
            obligateVO2 = new ObligateVO();
            BeanUtils.copyProperties(obligateVO1, obligateVO2);
            if(materialsScheduleDO.getType() == 1){
                obligateVO2.setSapInArea(materialsScheduleDO.getInLocation());
                obligateVO2.setSapOutArea(realSapCode);
            }else{
                obligateVO2.setSapInArea(materialsScheduleDO.getSapInArea());
                obligateVO2.setSapOutArea(realSapCode);
            }

            obligateVOList2.add(obligateVO2);*/
        }
        materialsScheduleMapper.add(materialsScheduleDO);
        if(materialsScheduleAddVO.getHeaderInfo().getType().equals(0)){
            WarehouseInboundVO warehouseInboundVO=new WarehouseInboundVO();
            warehouseInboundVO.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0,4));
            warehouseInboundVO.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
            warehouseInboundVO.setWarehouseCode(materialsScheduleDO.getInLocation());
            warehouseInboundVO.setInArea(materialsScheduleDO.getInArea());
            warehouseInboundVO.setSapInArea(materialsScheduleDO.getSapInArea());
            warehouseInboundVO.setAmount(num);
            warehouseInboundAddVO.setHeaderInfo(warehouseInboundVO);
            warehouseInboundAddVO.setDetailList(inDetailList);
            warehouseInboundService.add(warehouseInboundAddVO,materialsScheduleDO.getCreateId(),orgId);

        }else {
            WarehouseDeliveryVO deliveryVO = new WarehouseDeliveryVO();
            deliveryVO.setBusinessSingle(materialsScheduleDO.getRequisitionNo().substring(0,4));
            deliveryVO.setBusinessOrder(materialsScheduleDO.getRequisitionNo());
            deliveryVO.setWarehouseCode(materialsScheduleDO.getOutLocation());
            deliveryVO.setOutArea(materialsScheduleDO.getOutArea());
            deliveryVO.setSapOutArea(materialsScheduleDO.getSapOutArea());
            deliveryVO.setAmount(num);
            DeliveryAddVO.setHeaderInfo(deliveryVO);
            DeliveryAddVO.setDetailList(outDetailList);
            warehouseDeliveryService.add(DeliveryAddVO,materialsScheduleDO.getCreateId(),orgId);
        }

        //同步到SAP创建预留单
        /*ObligateHeaderVO headerVO = new ObligateHeaderVO();
        headerVO.setBusinesId(materialsScheduleDO.getId());
        headerVO.setBusinesOrder(materialsScheduleDO.getRequisitionNo());
        headerVO.setBusinesSingle(materialsScheduleDO.getRequisitionNo().substring(0, 4));
        sapCommonService.createObligateOrder(headerVO, obligateVOList1, obligateVOList2 , orgId);*/

        return ordNo;
    }

    @Transactional(rollbackFor = Exception.class)
    public synchronized ErrorCode auditPass(MaterialsScheduleAddVO materialsScheduleAddVO,String orgId) throws Exception {

        MaterialsScheduleDO item = materialsScheduleMapper.item(materialsScheduleAddVO.getHeaderInfo().getId());
        if (!ObjectUtils.isEmpty(item.getSapStatus()) && item.getSapStatus().equals(1)) {
            throw new Exception("已同步SAP!");
        }

        MaterialsScheduleVO materialsScheduleVO = materialsScheduleAddVO.getHeaderInfo();
        MaterialsScheduleDO materialsScheduleDO = new MaterialsScheduleDO();
        BeanUtils.copyProperties(materialsScheduleVO, materialsScheduleDO);
        materialsScheduleDO.setAuditStatus(1);
        materialsScheduleMapper.update(materialsScheduleDO);

        List<ObligateVO> obligateVOList1 = new ArrayList<>();
        List<ObligateVO> obligateVOList2 = new ArrayList<>();
        ObligateVO obligateVO1;
        ObligateVO obligateVO2;

        String realSapCode = TJ_DEFAULT_WAREHOUSE_CODE;
        DataDictionaryDO dictionaryDO = dataDictionaryMapper.itemByCode(CompanyConstants.MID_WAREHOUSE_CODE, orgId);
        if (null != dictionaryDO && StringUtils.isNotBlank(dictionaryDO.getName())) {
            realSapCode = dictionaryDO.getName();
        }

        for (MaterialsScheduleDetailVO detailVO : materialsScheduleAddVO.getDetailList()) {
            obligateVO1 = new ObligateVO();
            obligateVO1.setMaterialNo(detailVO.getMaterialsNo());
            obligateVO1.setAmount(detailVO.getAmount());
            obligateVO1.setMoveType(materialsScheduleDO.getSapType());
            if (materialsScheduleDO.getType() == 1) {
                obligateVO1.setSapOutArea(materialsScheduleDO.getSapOutArea());
                obligateVO1.setSapInArea(realSapCode);
            } else {
                obligateVO1.setSapOutArea(detailVO.getOutLocation());
                obligateVO1.setSapInArea(realSapCode);
            }
            obligateVOList1.add(obligateVO1);
            obligateVO2 = new ObligateVO();
            BeanUtils.copyProperties(obligateVO1, obligateVO2);
            if (materialsScheduleDO.getType() == 1) {
                obligateVO2.setSapInArea(materialsScheduleDO.getInLocation());
                obligateVO2.setSapOutArea(realSapCode);
            } else {
                obligateVO2.setSapInArea(materialsScheduleDO.getSapInArea());
                obligateVO2.setSapOutArea(realSapCode);
            }

            obligateVOList2.add(obligateVO2);
        }

        //同步到SAP创建预留单
        ObligateHeaderVO headerVO = new ObligateHeaderVO();
        headerVO.setBusinesId(materialsScheduleDO.getId());
        headerVO.setBusinesOrder(materialsScheduleDO.getRequisitionNo());
        headerVO.setBusinesSingle(materialsScheduleDO.getRequisitionNo().substring(0, 4));
        LogHelper.monitor("领料单审核，同步SAP创建预留单");
//        sapCommonService.createObligateOrder(headerVO, obligateVOList1, obligateVOList2, orgId);

        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode auditRefuse(MaterialsScheduleAddVO materialsScheduleAddVO){
        MaterialsScheduleVO materialsScheduleVO = materialsScheduleAddVO.getHeaderInfo();
        MaterialsScheduleDO materialsScheduleDO = new MaterialsScheduleDO();
        BeanUtils.copyProperties(materialsScheduleVO,materialsScheduleDO);
        materialsScheduleDO.setAuditStatus(0);
        materialsScheduleMapper.update(materialsScheduleDO);
        return ErrorCode.Success;
    }

    public List<MaterialsScheduleDO> getMaterialsScheduleByCrmOrder(String crmOrder){
        if (StringUtils.isEmpty(crmOrder)) {
            return null;
        }
        List<MaterialsScheduleDO> schedules = materialsScheduleMapper.findByCrmOrder(crmOrder);
        if (CollectionUtils.isEmpty(schedules)) {
            return null;
        }
        return schedules;
    }

//    @Transactional(rollbackFor = Exception.class)
//    public ErrorCode syncCrm(String id){
//        MaterialsScheduleDO materialsScheduleDO = materialsScheduleMapper.item(id);
//        if (!StringUtil.isNullOrEmpty(materialsScheduleDO.getCrmOrder())){
//            return ErrorCode.Success;
//        }
//        List<MaterialsScheduleDetailDO> listDO = materialsScheduleDetailMapper.listForLocationUser(id);
//        boolean isSuccess = true;
//
//        MaterialsScheduleDO updateDO = new MaterialsScheduleDO();
//        updateDO.setId(materialsScheduleDO.getId());
//        for (MaterialsScheduleDetailDO materialsScheduleDetailDO : listDO) {
//            Map resultMap = syncCrm(materialsScheduleDO.getRequisitionNo(), materialsScheduleDetailDO.getMaterialsNo(), materialsScheduleDetailDO.getRealAmount(), materialsScheduleDO);
//
//            //同步失败需要回写
//            if (resultMap.get("Flag") != null && resultMap.get("Flag").equals(false)){
//                String msg = updateDO.getSyncCrmMsg() == null ? "" : updateDO.getSyncCrmMsg();
//                msg += resultMap.get("Msg").toString() + ";";
//                updateDO.setSyncCrmFlag("2");
//                updateDO.setSyncCrmMsg(msg);
//                isSuccess = false;
//            }
//        }
//
//        if (isSuccess){
//            updateDO.setSyncCrmFlag("1");
//            updateDO.setSyncCrmMsg("操作成功");
//        }
//
//        materialsScheduleMapper.update(updateDO);
//        return ErrorCode.Success;
//    }

    public Integer countAuditData(String orgId) {
        Integer result = materialsScheduleMapper.countAuditData(orgId);
        return result;
    }

    /**
     * @Des 备件从生产领料选择发货通知单数据查询
     * @Date 2021/6/1 17:31
     * @Author wangzhaoyu
     * @Param [deliveryNoteNo, pageNum, pageSize]
     * @Return yb.ecp.fast.infra.infra.PageCommonVO<xcmg.device.service.vo.materialsSchedule.SelectDeliveryNoteVO>
     */
    public PageCommonVO<SelectDeliveryNoteVO> selectDeliveryNotes(String orgId,String deliveryNoteNo, Integer pageNum, Integer pageSize) {
        PageHelperPlus.startPage(pageNum, pageSize);
        PageHelperPlus.orderBy("create_date desc");
        DeliveryNoteVO queryCondition = new DeliveryNoteVO();
        queryCondition.setSupplierOrgId(orgId);
        queryCondition.setDeliveryNo(deliveryNoteNo);
        List<DeliveryNoteDO> dataLst = deliveryNoteMapper.list(queryCondition);
        List<SelectDeliveryNoteVO> deliveryNotes = new LinkedList<>();
        for (DeliveryNoteDO deliveryNoteDO : dataLst) {
            SelectDeliveryNoteVO deliveryNoteVO = new SelectDeliveryNoteVO();
            deliveryNoteVO.setId(deliveryNoteDO.getId());
            deliveryNoteVO.setDeliveryNo(deliveryNoteDO.getDeliveryNo());
            deliveryNoteVO.setPurchaseOrgName(deliveryNoteDO.getPurchaseOrgName());
            deliveryNotes.add(deliveryNoteVO);
        }
        PageCommonVO<SelectDeliveryNoteVO> result = new PageCommonVO<>();
        result.setPageInfo(new PageInfo(dataLst));
        result.setPageInfoList(deliveryNotes);
        return result;
    }

    public List<MaterialsScheduleDeliveryNoteDetailVO> deliveryNoteDetails(String deliveryNoteId) {
       if(StringUtils.isEmpty(deliveryNoteId)){
           return Collections.EMPTY_LIST;
       }
       List<MaterialsScheduleDeliveryNoteDetailVO> dataLst = deliveryNoteDetailMapper.materialsScheduleSelectDeliveryNoteDetails(deliveryNoteId);
       return dataLst;
    }
}
